var __extends = (this && this.__extends) || (function () {
    var extendStatics = function (d, b) {
        extendStatics = Object.setPrototypeOf ||
            ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
            function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
        return extendStatics(d, b);
    };
    return function (d, b) {
        if (typeof b !== "function" && b !== null)
            throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
        extendStatics(d, b);
        function __() { this.constructor = d; }
        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    };
})();
// 在ES6以前，js通过构造函数的方式来实现类的概念；在ES6中，可以直接使用class来声明一个类。ts在ES6的基础上，新增了类的一些特性
// 定义一个类，一般来说有属性、方法、构造函数，在通过new实例化类时，会自动调用构造函数。
// 静态属性和静态方法属于类，只能通过类访问，而不能通过类的实例访问
var Car = /** @class */ (function () {
    function Car(name) {
        this.name = name;
    }
    ; // 构造函数
    Car.prototype.run = function () { };
    ; // 方法
    Car.say = function () { };
    ; // 静态方法
    return Car;
}());
var car = new Car('car'); // 实例化
// 类的继承
// 继承采用关键词extends，子类继承父类的非私有属性和方法，子类中可通过super来访问父类的构造函数和方法
var ACar = /** @class */ (function (_super) {
    __extends(ACar, _super);
    function ACar(name) {
        return _super.call(this, name) || this;
    }
    ACar.prototype.run = function () {
        _super.prototype.run.call(this);
    };
    return ACar;
}(Car));
// 修饰符：public、private、protected
// 修饰符可用于修饰属性和方法，具体来说：
// public表示公有的，其修饰的属性和方法在任务地方都可以被访问，受限是最小的，默认为public
// private表示私有的，其修饰的属性和方法只能在当前类中使用，不能在其子类或者其他类中访问，受限是最大的
// protected表示受保护的，其修饰的属性和方法只能在当前类和子类中访问，受限适中
// 对于构造函数，如果用private修饰，表示不可被实例化，也不能被继承
var Car2 = /** @class */ (function () {
    function Car2(name) {
    }
    return Car2;
}());
// new Car2('hello'); // 编译错误
// 如果是用protected修饰构造函数，则表示不可被实例化，只能被继承
var Car3 = /** @class */ (function () {
    function Car3(name) {
    }
    return Car3;
}());
var Car4 = /** @class */ (function (_super) {
    __extends(Car4, _super);
    function Car4() {
        return _super !== null && _super.apply(this, arguments) || this;
    }
    return Car4;
}(Car3));
// new Car3('hello'); // 编译错误
// abstract 抽象类和抽象方法
// 使用abstract修饰的类为抽象类，抽象类不可被实例化，只能用于继承。
// 抽象类可以有成员属性和成员方法，不一定有抽象方法；有抽象方法的类一定是抽象类。
// 抽象方法只能定义，不能有具体的实现；子类继承抽象类时，必需实现抽象类的抽象方法。
var Car5 = /** @class */ (function () {
    function Car5(name) {
        this.name = name;
    }
    ;
    Car5.prototype.say = function () {
        console.log('hello world');
    };
    ;
    return Car5;
}());
var Car6 = /** @class */ (function (_super) {
    __extends(Car6, _super);
    function Car6() {
        return _super !== null && _super.apply(this, arguments) || this;
    }
    Car6.prototype.run = function () {
        console.log('world hello'); // 子类必需实现抽象方法
    };
    return Car6;
}(Car5));
// 给类指定类型
// 我们可以给类的实例指定类型，常见于多态
var Animal = /** @class */ (function () {
    function Animal() {
    }
    return Animal;
}());
var Cat = /** @class */ (function (_super) {
    __extends(Cat, _super);
    function Cat() {
        return _super !== null && _super.apply(this, arguments) || this;
    }
    Cat.prototype.eat = function () {
        console.log('cat eat');
    };
    return Cat;
}(Animal));
var Dog = /** @class */ (function (_super) {
    __extends(Dog, _super);
    function Dog() {
        return _super !== null && _super.apply(this, arguments) || this;
    }
    Dog.prototype.eat = function () {
        console.log('dog eat');
    };
    return Dog;
}(Animal));
var a = new Dog();
a = new Cat();
a.eat();
